using System;
using UnityEngine;

public class Model : MonoBehaviour
{
	private Profile cacheProfile;

	private Setting.NextBoostAtLevel[] nextBoostAtLevel;

	[SerializeField]
	private Setting setting;

	public double GetMineUnlockPrice(Mineral mineral)
	{
		Setting.Mine mine = Array.Find(setting.mine, (Setting.Mine target) => target.mineral == mineral);
		return mine.baseUnlockPrice;
	}

	public double GetPrestigePrice(Mineral mineral, int reset)
	{
		Setting.Mine mine = Array.Find(setting.mine, (Setting.Mine target) => target.mineral == mineral);
		return Math.Round(mine.baseUnlockPrice * Math.Pow(mine.resetPriceFactor, reset));
	}

	public int GetSuperCashBonusOnReset(Mineral mineral)
	{
		Setting.Mine mine = Array.Find(setting.mine, (Setting.Mine target) => target.mineral == mineral);
		return mine.superCashBonus;
	}

	public float GetMineMultiplier(Mineral mineral, int reset)
	{
		Setting.Mine mine = Array.Find(setting.mine, (Setting.Mine target) => target.mineral == mineral);
		float num = (float)reset * mine.multiplierFactor;
		if (num == 0f)
		{
			num = 1f;
		}
		return (float)Math.Round((float)mine.baseMultiplier * num, 1);
	}

	public Profile GetManagerProfile(Position position, double price)
	{
		int num = 0;
		int num2 = 0;
		cacheProfile = new Profile();
		cacheProfile.position = position;
		cacheProfile.price = price;
		num = 0;
		for (int i = 0; i < setting.recruiment.experienceRate.Length; i++)
		{
			num += setting.recruiment.experienceRate[i].rate;
		}
		num2 = UnityEngine.Random.Range(0, num);
		for (int j = 0; j < setting.recruiment.experienceRate.Length; j++)
		{
			if (num2 <= setting.recruiment.experienceRate[j].rate)
			{
				cacheProfile.experience = setting.recruiment.experienceRate[j].experience;
				break;
			}
			num2 -= setting.recruiment.experienceRate[j].rate;
		}
		num = 0;
		for (int k = 0; k < setting.recruiment.skillRate.Length; k++)
		{
			num += setting.recruiment.skillRate[k].rate;
		}
		do
		{
			num2 = UnityEngine.Random.Range(0, num);
			for (int l = 0; l < setting.recruiment.skillRate.Length; l++)
			{
				if (num2 <= setting.recruiment.skillRate[l].rate)
				{
					cacheProfile.skill = setting.recruiment.skillRate[l].skill;
					break;
				}
				num2 -= setting.recruiment.skillRate[l].rate;
			}
		}
		while ((position == Position.Elevator && cacheProfile.skill == Skill.MiningSpeed) || (position == Position.Elevator && cacheProfile.skill == Skill.WalkingSpeed) || (position == Position.Warehouse && cacheProfile.skill == Skill.MiningSpeed) || (position == Position.Warehouse && cacheProfile.skill == Skill.MovementSpeed) || (position == Position.MineShaft && cacheProfile.skill == Skill.LoadExpansion) || (position == Position.MineShaft && cacheProfile.skill == Skill.MovementSpeed) || (position == Position.MineShaft && cacheProfile.skill == Skill.LoadingSpeed));
		Setting.SkillEffective skillEffective = Array.Find(setting.recruiment.skillEffective, (Setting.SkillEffective target) => target.skill == cacheProfile.skill && target.experience == cacheProfile.experience);
		cacheProfile.cooldown = skillEffective.cooldown;
		cacheProfile.maintain = skillEffective.maintain;
		cacheProfile.effective = skillEffective.effective;
		return cacheProfile;
	}

	public double GetInstantCash(double idleCash)
	{
		double num = Math.Round(idleCash * (double)setting.cash.instantCashDuration);
		return (!(num > 0.0)) ? ((double)setting.cash.instantCashDefault) : num;
	}

	public int GetMineShaftPriceWithSuperCash(int floor, double idleCash)
	{
		double mineShaftPriceWithCash = GetMineShaftPriceWithCash(floor);
		int value = (int)(mineShaftPriceWithCash / idleCash / 60.0);
		return Mathf.Clamp(value, setting.mineShaft.minSuperCashUnlock, setting.mineShaft.maxSuperCashUnlock);
	}

	public Fence.Properties GetFenceProperty(int floor)
	{
		int num = floor / setting.mineShaft.barrierUnlockStep - 1;
		Fence.Properties result = default(Fence.Properties);
		result.cashPrice = Math.Round(GetMineShaftPriceWithCash(floor) / (double)setting.mineShaft.unlockBarrierFactor);
		result.duration = setting.blockUnlockAtFloor[num].blockTime;
		result.superCashPrice = setting.blockUnlockAtFloor[num].superCashToUnlock;
		result.reduced = setting.blockUnlockAtFloor[num].processReduceTime;
		result.remaining = result.duration;
		result.process = false;
		result.locked = true;
		return result;
	}

	public int GetNextBoostAtLevel(int level, Position position)
	{
		int result = int.MaxValue;
		switch (position)
		{
		case Position.Elevator:
			nextBoostAtLevel = setting.elevator.nextBoostAtLevel;
			break;
		case Position.MineShaft:
			nextBoostAtLevel = setting.mineShaft.nextBoostAtLevel;
			break;
		case Position.Warehouse:
			nextBoostAtLevel = setting.warehouse.nextBoostAtLevel;
			break;
		}
		if (level > nextBoostAtLevel[nextBoostAtLevel.Length - 1].level)
		{
			return result;
		}
		for (int i = 0; i < nextBoostAtLevel.Length; i++)
		{
			if (level < nextBoostAtLevel[i].level)
			{
				result = nextBoostAtLevel[i].level;
				break;
			}
		}
		return result;
	}

	public int GetLastBoostAtLevel(int level, Position position)
	{
		int result = 0;
		switch (position)
		{
		case Position.Elevator:
			nextBoostAtLevel = setting.elevator.nextBoostAtLevel;
			break;
		case Position.MineShaft:
			nextBoostAtLevel = setting.mineShaft.nextBoostAtLevel;
			break;
		case Position.Warehouse:
			nextBoostAtLevel = setting.warehouse.nextBoostAtLevel;
			break;
		}
		if (level < nextBoostAtLevel[0].level)
		{
			return result;
		}
		for (int i = 0; i < nextBoostAtLevel.Length; i++)
		{
			if (level < nextBoostAtLevel[i].level)
			{
				result = nextBoostAtLevel[i - 1].level;
				break;
			}
		}
		return result;
	}

	public int GetSuperCashBonus(int nextLevel, int currentLevel, Position position)
	{
		int num = 0;
		switch (position)
		{
		case Position.Elevator:
			nextBoostAtLevel = setting.elevator.nextBoostAtLevel;
			break;
		case Position.MineShaft:
			nextBoostAtLevel = setting.mineShaft.nextBoostAtLevel;
			break;
		case Position.Warehouse:
			nextBoostAtLevel = setting.warehouse.nextBoostAtLevel;
			break;
		}
		if (currentLevel > nextBoostAtLevel[nextBoostAtLevel.Length - 1].level)
		{
			return num;
		}
		for (int i = 0; i < nextBoostAtLevel.Length; i++)
		{
			if (nextBoostAtLevel[i].level > currentLevel && nextBoostAtLevel[i].level <= nextLevel)
			{
				num += nextBoostAtLevel[i].superCash;
			}
		}
		return num;
	}

	public double GetManagerPrice(int count, Position position)
	{
		switch (position)
		{
		case Position.Elevator:
			return Math.Round((double)setting.elevator.baseManagerPrice * Math.Pow(setting.elevator.hireManagerFactor, count));
		case Position.MineShaft:
			return Math.Round((double)setting.mineShaft.baseManagerPrice * Math.Pow(setting.mineShaft.hireManagerFactor, count));
		case Position.Warehouse:
			return Math.Round((double)setting.warehouse.baseManagerPrice * Math.Pow(setting.warehouse.hireManagerFactor, count));
		default:
			return 0.0;
		}
	}

	public double GetMineShaftPriceWithCash(int floor)
	{
		int barrierUnlockStep = setting.mineShaft.barrierUnlockStep;
		float unlockBarrierFactor = setting.mineShaft.unlockBarrierFactor;
		return Math.Round((double)setting.mineShaft.baseUnlockPrice * Math.Pow(setting.mineShaft.unlockPriceFactor, floor) * Math.Pow(unlockBarrierFactor, floor / barrierUnlockStep));
	}

	public double GetTotalPerformance(int loop, float distance, float speed, double performance, double capacity)
	{
		return Math.Round(capacity / (capacity / performance * (double)loop + (double)(distance * 2f / speed)));
	}

	public double GetUpgradePrice(int floor, int currentLevel, int step, Position position)
	{
		float num = 0f;
		double num2 = 0.0;
		switch (position)
		{
		case Position.Elevator:
			num2 = setting.elevator.baseUpgradePrice;
			num = setting.elevator.upgradePriceFactor;
			break;
		case Position.MineShaft:
			num2 = GetMineShaftPriceWithCash(floor);
			num = setting.mineShaft.upgradePriceFactor;
			break;
		case Position.Warehouse:
			num2 = setting.warehouse.baseUpgradePrice;
			num = setting.warehouse.upgradePriceFactor;
			break;
		}
		float num3 = (num + 100f) / 100f;
		return Math.Round(num2 * ((Math.Pow(num3, currentLevel + step) - Math.Pow(num3, currentLevel)) / (double)(num3 - 1f)));
	}

	public int GetMaxUpgradeLevel(double cash, int floor, int currentLevel, Position position, int reduce)
	{
		float num = 0f;
		switch (position)
		{
		case Position.Elevator:
			num = setting.elevator.upgradePriceFactor;
			break;
		case Position.MineShaft:
			num = setting.mineShaft.upgradePriceFactor;
			break;
		case Position.Warehouse:
			num = setting.warehouse.upgradePriceFactor;
			break;
		}
		float num2 = (num + 100f) / 100f;
		double upgradePrice = GetUpgradePrice(floor, currentLevel, 1, position);
		upgradePrice -= upgradePrice / 100.0 * (double)reduce;
		return (int)Math.Log(cash / upgradePrice * (double)(num2 - 1f) + 1.0, num2);
	}

	public MineShaft.Properties GetMineShaftProperty(float distance, int floor, int currentLevel, int step, float multiplier)
	{
		MineShaft.Properties result = default(MineShaft.Properties);
		double mineShaftPriceWithCash = GetMineShaftPriceWithCash(floor);
		double num = (double)setting.mineShaft.workerCapacityFactor / Math.Pow(setting.mineShaft.workerCapacityFactor, floor);
		float num2 = (setting.mineShaft.upgradeBonusFactor + 100f) / 100f;
		int num3 = 0;
		for (int i = 0; i < setting.mineShaft.minerBoostAtLevel.Length; i++)
		{
			if (currentLevel + step >= setting.mineShaft.minerBoostAtLevel[i])
			{
				num3++;
			}
		}
		result.floor = floor;
		result.level = currentLevel + step;
		result.walkingSpeed = setting.mineShaft.defaultWalkingSpeed;
		result.miners = setting.mineShaft.defaultMiners + num3;
		result.workerCapacity = Math.Round(mineShaftPriceWithCash * num * Math.Pow(num2, currentLevel + step - 1) * (double)multiplier);
		result.miningSpeed = Math.Round(result.workerCapacity / (double)setting.mineShaft.defaultMiningTime);
		result.totalExtraction = GetTotalPerformance(1, distance, result.walkingSpeed, result.miningSpeed, result.workerCapacity);
		return result;
	}

	public Elevator.Properties GetElevatorProperty(float distance, int currentLevel, int step)
	{
		Elevator.Properties result = default(Elevator.Properties);
		int baseUpgradePrice = setting.elevator.baseUpgradePrice;
		float num = (setting.elevator.loadFactor + 100f) / 100f;
		float num2 = (setting.elevator.upgradeLoadBonusFactor + 100f) / 100f;
		result.level = currentLevel + step;
		result.load = Math.Round((double)(num * (float)baseUpgradePrice) * Math.Pow(num2, currentLevel + step - 1));
		result.loadingSpeed = Math.Round(result.load / setting.elevator.defaultLoadingTime);
		result.movementSpeed = (float)Math.Round(setting.elevator.defaultMovementSpeed + (float)(currentLevel + step) * (setting.elevator.defaultMovementSpeed * (setting.elevator.movementSpeedFactor / 100f)), 2);
		result.totalTransportation = GetTotalPerformance(1, distance, result.movementSpeed, result.loadingSpeed, result.load);
		return result;
	}

	public Warehouse.Properties GetWarehouseProperty(float distance, int currentLevel, int step)
	{
		Warehouse.Properties result = default(Warehouse.Properties);
		int baseUpgradePrice = setting.warehouse.baseUpgradePrice;
		float num = (setting.warehouse.loadFactor + 100f) / 100f;
		float num2 = (setting.elevator.upgradeLoadBonusFactor + 100f) / 100f;
		int num3 = 0;
		for (int i = 0; i < setting.warehouse.transporterBoostAtLevel.Length; i++)
		{
			if (currentLevel + step >= setting.warehouse.transporterBoostAtLevel[i])
			{
				num3++;
			}
		}
		result.level = currentLevel + step;
		result.transporter = setting.warehouse.defaultTransporter + num3;
		result.loadPerTransporter = Math.Round((double)(num * (float)baseUpgradePrice) * Math.Pow(num2, currentLevel + step - 1));
		result.loadingSpeed = Math.Round(result.loadPerTransporter / (double)setting.warehouse.defaultLoadingTime);
		result.walkingSpeed = setting.warehouse.defaultWalkingSpeed;
		result.totalTransportation = GetTotalPerformance(2, distance, result.walkingSpeed, result.loadingSpeed, result.loadPerTransporter);
		return result;
	}
}
